import shutil
import json
import traceback

from django.conf import settings
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.shortcuts import render_to_response
from django.utils.safestring import mark_safe

from rest_framework.decorators import api_view
from rest_framework import status
from rest_framework.response import Response

from XApiTestServer.serializers import *
from XApiTestServer.tasks import main_hrun

from XApiTestServer.utils.common import *
from XApiTestServer.utils.response import *
from XApiTestServer.utils.auth import get_username
from XApiTestServer.utils.test_generator import get_test_base_dir, gen_by_batch, gen_test_by_type
from XApiTestServer.utils.test_report import *
from XApiTestServer.utils.test_report_summary import gen_summary_report

from httprunner.api import HttpRunner

import logging


logger = logging.getLogger('XApiTestServer')


"""
                         _oo0oo_
                        o8888888o
                        88" . "88
                        (| -_- |)
                        0\  =  /0
                      ___/`---'\___
                    .' \\|     |// '.
                   / \\|||  :  |||// \
                  / _||||| -:- |||||- \
                 |   | \\\  -  /// |   |
                 | \_|  ''\---/''  |_/ |
                 \  .-\__  '-'  ___/-. /
               ___'. .'  /--.--\  `. .'___
            ."" '<  `.___\_<|>_/___.' >' "".
           | | :  `- \`.;`\ _ /`;.`/ - ` : | |
           \  \ `_.   \_ __\ /__ _/   .-` /  /
       =====`-.____`.___ \_____/___.-`___.-'=====
                         `=---='
  
  
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
                 佛祖保佑         永无BUG

"""
# Create your views for api_server here.
RUN_TYPE = ["project", "module", "suite", "case"]


def _validate_run_parameter(gen_type, index, cfg_id):
    if gen_type not in RUN_TYPE:
        msg = 'type(运行类型)不合法'
        return Response(response_format(VERIFY_FIELDS_HINT, msg), status=status.HTTP_200_OK)
    logger.info("Run type:{gen_type}".format(gen_type=gen_type))

    if not index:
        msg = 'id为空，该字段为必填字段'
        return Response(response_format(VERIFY_FIELDS_HINT, msg), status=status.HTTP_200_OK)

    if not cfg_id:
        msg = '配置ID为空，该字段为必填字段'
        return Response(response_format(VERIFY_FIELDS_HINT, msg), status=status.HTTP_200_OK)

def run_test(request):
    """
    运行测试套件/项目/模块/用例
    :param request:
    :return:
    """
    token = request.META.get("HTTP_X_TOKEN", None)
    account_name = get_username(token)

    kwargs = json.loads(request.body.decode('utf-8'))
    gen_type = kwargs.pop('type')
    index = kwargs.pop('id')
    cfg_id = kwargs.pop('cfg_id')
    back_async = kwargs.pop('back_async', 0)
    summary_flag = kwargs.pop('summary_flag', 0)
    product_name = kwargs.pop('product_name', '')

    # Step01 validate request parameter
    _validate_run_parameter(gen_type, index, cfg_id)

    # Step02 generate test file(yaml)
    test_base_dir = get_test_base_dir(gen_type)
    try:
        gen_test_by_type(gen_type, index, test_base_dir, cfg_id)
    except Exception as e:
        traceback.print_exc()
        response_body = RUN_TEST_EXCEPTION
        response_body['msg'] = e
        return JsonResponse(response_body, encoder=ResponseExceptionEncoder,
                            json_dumps_params={'ensure_ascii': False})

    # Step03 run test in httprunner
    if back_async:
        logger.info('Return None after ASYNC run.')

        main_hrun.delay(test_base_dir, report_name)
        return HttpResponse('用例执行中，请稍后查看报告即可,默认时间戳命名报告')
    else:
        logger.info('Return the json format report after SYNC run.')

        run_kwargs = {
            "failfast": False,
        }
        runner = HttpRunner(**run_kwargs)

        if gen_type == "suite":
            suite_name = TestSuite.objects.get(id=index).suite_name
            suite_yml_path = os.path.join(test_base_dir, "{}.yml".format(suite_name))
            logger.info("Test suite yml file base path:{path}".format(path=suite_yml_path))
            runner.run(suite_yml_path)
        else:
            logger.info("Test case yml file base directory:{dir}".format(dir=test_base_dir))
            runner.run(test_base_dir)

        if not settings.DEBUG:
            # 删除yml文件,异常的时候不删除，可以用来debug
            shutil.rmtree(test_base_dir)

        report_name = get_test_name(index, gen_type)
        report_id = add_test_report(runner, account_name, report_name)

        runner._summary = summary_response(runner.summary)
        runner._summary.setdefault("report_id", report_id)
        runner._summary.setdefault("report_name", runner.summary['report_name'])
        runner._summary.setdefault("report_html_url", get_html_report_url(report_id))

        if summary_flag:
            # generate html summary report file
            gen_summary_report(runner._summary, report_id, 'test', msg=None)
            runner._summary.setdefault("sum_report_html_url", get_html_summary_report_url(report_id))

        logger.info("Runner _Summary({}): {}".format(type(runner._summary), runner._summary))

        RUN_TEST_SUCCESS['data'] = runner._summary

        return JsonResponse(RUN_TEST_SUCCESS, json_dumps_params={'ensure_ascii': False})

def run_batch_test(request):
    """
    生成批量运行用例
    :param request:
    :return:
    """
    token = request.META.get("HTTP_X_TOKEN", None)
    account_name = get_username(token)

    kwargs = json.loads(request.body.decode('utf-8'))
    gen_type = kwargs.pop('type')
    index_list = kwargs.pop('id')
    cfg_id = kwargs.pop('cfg_id')
    back_async = kwargs.pop('back_async', 0)
    summary_flag = kwargs.pop('summary_flag', 0)
    product_name = kwargs.pop('product_name', '')

    # Step01 validate request parameter
    _validate_run_parameter(gen_type, index_list, cfg_id)

    # Step02 generate test file(yaml)
    test_base_dir = get_test_base_dir(gen_type)
    try:
        gen_by_batch(gen_type, index_list, test_base_dir, cfg_id)
    except Exception as e:
        traceback.print_exc()
        response_body = RUN_TEST_EXCEPTION
        response_body['msg'] = e
        return JsonResponse(response_body, encoder=ResponseExceptionEncoder,
                            json_dumps_params={'ensure_ascii': False})

    # Step03 run test in httprunner
    if back_async:
        logger.info('Return None after ASYNC run.')

        main_hrun.delay(test_base_dir, report_name)
        return HttpResponse('用例执行中，请稍后查看报告即可,默认时间戳命名报告')
    else:
        logger.info('Return the json format report after SYNC run.')

        run_kwargs = {
            "failfast": False,
        }
        runner = HttpRunner(**run_kwargs)

        if gen_type == "suite":
            suite_name = TestSuite.objects.get(id=index).suite_name
            suite_yml_path = os.path.join(test_base_dir, "{}.yml".format(suite_name))
            logger.info("Test suite yml file base path:{path}".format(path=suite_yml_path))
            runner.run(suite_yml_path)
        else:
            logger.info("Test case yml file base directory:{dir}".format(dir=test_base_dir))
            runner.run(test_base_dir)

        if not settings.DEBUG:
            # 删除yml文件,异常的时候不删除，可以用来debug
            shutil.rmtree(test_base_dir)

        report_name = get_test_name(index, gen_type)
        report_id = add_test_report(runner, account_name, report_name)

        runner._summary = summary_response(runner.summary)
        runner._summary.setdefault("report_id", report_id)
        runner._summary.setdefault("report_name", runner.summary['report_name'])
        runner._summary.setdefault("report_html_url", get_html_report_url(report_id))

        if summary_flag:
            # generate html summary report file
            gen_summary_report(runner._summary, report_id, 'test', msg=None)
            runner._summary.setdefault("sum_report_html_url", get_html_summary_report_url(report_id))

        logger.info("Runner _Summary({}): {}".format(type(runner._summary), runner._summary))

        RUN_TEST_SUCCESS['data'] = runner._summary

        return JsonResponse(RUN_TEST_SUCCESS, json_dumps_params={'ensure_ascii': False})
